package fr.inserm.u674.chcdbweb.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import fr.inserm.u674.chcdbweb.Config;
import fr.inserm.u674.chcdbweb.model.DAO.DAOException;
import fr.inserm.u674.chcdbweb.model.DAO.EAVModalityDAO;
import fr.inserm.u674.chcdbweb.model.DAO.EAVVariableDAO;
import fr.inserm.u674.chcdbweb.model.DAO.TissueDAO;
import fr.inserm.u674.chcdbweb.model.DAO.TissueExtractionDAO;
import fr.inserm.u674.chcdbweb.model.DAO.TissueTypeDAO;
import fr.inserm.u674.chcdbweb.model.DTO.EAVModality;
import fr.inserm.u674.chcdbweb.model.DTO.EAVVariable;
import fr.inserm.u674.chcdbweb.model.DTO.Tissue;
import fr.inserm.u674.chcdbweb.model.DTO.TissueExtraction;
import fr.inserm.u674.chcdbweb.model.DTO.TissueType;
import fr.inserm.u674.chcdbweb.model.feed.ExtractionFeeder;
import fr.inserm.u674.chcdbweb.model.feed.FeederException;
import fr.inserm.u674.chcdbweb.model.files.GridFileSaver;
import fr.inserm.u674.chcdbweb.model.forms.ExtractionListForm;
import fr.inserm.u674.chcdbweb.view.ajax.dhmlx.DHTMLXWriter;

/**
 * @author Thomas Burguiere Servlet implementation class CHCDBWebServlet
 */
public class CHCDBWebServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	private static final String ATTRIBUTE_INDEX_PAGE_VIEW = "index.jsp";
	// private static final String ATTRIBUTE_ERROR_PAGE_VIEW = "error.jsp";

	// display tissue constants
	private static final String ATTRIBUTE_DISPLAY_TISSUE_VIEW = "displayTissue.jsp";
	private static final String ATTRIBUTE_TISSUE = "tissue";

	// list extractions constants
	private static final String ATTRIBUTE_LIST_EXTRACTION_VIEW = "extractionList.jsp";
	private static final String ATTRIBUTE_LIST_EXTRACTION_FORM = "extractionListForm";
	private static final String ATTRIBUTE_EXTRACTION_LIST = "extractionList";

	// list eav variables constants
	private TissueDAO tissueDAO;
	private TissueTypeDAO tissueTypeDAO;
	private TissueExtractionDAO tissueExtractionDAO;
	private EAVVariableDAO eavVariableDAO;
	private EAVModalityDAO eavModalityDAO;

	@Override
	public void init() throws ServletException {
		tissueDAO = Config.getInstance(getServletContext()).getDAOFactory().getTissueDAO();
		tissueTypeDAO = Config.getInstance(getServletContext()).getDAOFactory().getTissueTypeDAO();
		tissueExtractionDAO =
			Config.getInstance(getServletContext()).getDAOFactory().getTissueExtractionDAO();
		Config.getInstance(getServletContext()).getDAOFactory().getUserDAO();
		eavVariableDAO =
			Config.getInstance(getServletContext()).getDAOFactory().getEavVariableDAO();
		eavModalityDAO =
			Config.getInstance(getServletContext()).getDAOFactory().getEavModalityDAO();
	}

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public CHCDBWebServlet() {
		super();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {

		String appAction = null;
		if (request.getParameter("appAction") != null
			&& request.getParameter("appAction").length() > 0) {
			appAction = request.getParameter("appAction");
			if (appAction.equalsIgnoreCase("displayTissue")) {
				doDisplayTissue2(request, response);
			}
			else if (appAction.equalsIgnoreCase("listExtractions")) {
				doListExtractions(request, response);
			}

			// called from extractionList.jsp when displayin the extraction grid
			else if (appAction.equalsIgnoreCase("ajaxListExtractions")) {
				doAjaxListExtractions(request, response);
			}

			// called from tissueList.jsp when displaying the dynamic tissue grid
			else if (appAction.equalsIgnoreCase("ajaxListTissues")) {
				doAjaxListTissues(request, response);
			}

			// called from tissueList.jsp when saving the dynamic tissue grid as an excel file
			else if (appAction.equalsIgnoreCase("ajaxSaveGrid")) {
				doAjaxSaveGridFile(request, response);
			}

			else if (appAction.equalsIgnoreCase("ajaxListVars")) {
				doAjaxListVars(request, response);
			}

			// called from variableList.jsp
			else if (appAction.equalsIgnoreCase("ajaxSubmitVar")) {
				doAjaxSubmitVar(request, response);
			}

			// called from variableList.jsp
			else if (appAction.equalsIgnoreCase("ajaxDeleteVars")) {
				doAjaxDeleteVars(request, response);
			}

			// called from variableList.jsp
			else if (appAction.equalsIgnoreCase("ajaxUpdateEAVVariable")) {
				doAjaxUpdateEAVVariable(request, response);
			}

			// called from variableList.jsp when displaying a variable info
			else if (appAction.equalsIgnoreCase("ajaxGetModalityGrid")) {
				doAjaxGetModalityGrid(request, response);
			}

			// called from variableList.jsp when displaying the distinct modality values of a single
			// EAVVariable
			else if (appAction.equalsIgnoreCase("ajaxLoadOldModalities")) {
				doAjaxLoadOldModalities(request, response);
			}

			// Unification of the two methods above, called from variableList.jsp when displaying
			// the distinct modality values of a single EAVVariable
			else if (appAction.equalsIgnoreCase("ajaxLoadModalityGridAndModalityList")) {
				doAjaxLoadModalityGridAndModalityList(request, response);
			}

			// called from variableList.jsp when displaying the distinct modality values of a single
			// EAVVariable
			else if (appAction.equalsIgnoreCase("ajaxUpdateModalityByVariableNameAndModalityValue")) {
				doAjaxUpdateModalityByVariableNameAndModalityValue(request, response);
			}

			// called from displayVariable.jsp
			else if (appAction.equalsIgnoreCase("ajaxFetchVarNames")) {
				doAjaxFetchVarNames(request, response);
			}

			// called from displayVariable.jsp
			else if (appAction.equalsIgnoreCase("ajaxFetchVar")) {
				doAjaxFetchVar(request, response);
			}

			else if (appAction.equalsIgnoreCase("ajaxLoadVarsComboBoxes")) {
				doAjaxLoadVarsComboBoxes(request, response);
			}
			else if (appAction.equalsIgnoreCase("ajaxLoadVarsArray")) {
				doAjaxLoadVarsArray(request, response);
			}

			// called from displayTissue.jsp when displaying a single tissue
			else if (appAction.equalsIgnoreCase("ajaxLoadTissue")) {
				doAjaxLoadTissue(request, response);
			}

			else if (appAction.equalsIgnoreCase("ajaxLoadAllEAVVariables")) {
				doAjaxLoadAllEAVVariables(request, response);
			}

			// called from newTissue.jsp when creating a single tissue
			else if (appAction.equalsIgnoreCase("ajaxLoadTissueList")) {
				doAjaxLoadTissueList(request, response);
			}

			// called from displayTissue.jsp when updating a single tissue
			else if (appAction.equalsIgnoreCase("ajaxUpdateTissueModalities")) {
				doAjaxUpdateTissueEAVModalities(request, response);
			}

			// called from displayTissue.jsp when adding a generic variable modality for a single
			// tissue
			else if (appAction.equalsIgnoreCase("ajaxLoadUnsetGenericVariables")) {
				doAjaxLoadUnsetGenericVariables(request, response);
			}

			// called from displayTissue.jsp when removing the master Tissue from a single
			// tissue
			else if (appAction.equalsIgnoreCase("ajaxDissociateMasterTissue")) {
				doAjaxDissociateMasterTissue(request, response);
			}

			// called from displayTissue.jsp when associating a new master Tissue to a single
			// tissue
			else if (appAction.equalsIgnoreCase("ajaxAssociateNewTissueWithMaster")) {
				doAjaxAssociateNewTissueWithMaster(request, response);
			}

			// called from newDelTissue.jsp when creating a new tissue
			else if (appAction.equalsIgnoreCase("ajaxLoadTissueTypes")) {
				doAjaxLoadTissueTypes(request, response);
			}

			// called from newDelTissue.jsp when creating a new tissue type
			else if (appAction.equalsIgnoreCase("ajaxCreateNewTissueType")) {
				doAjaxCreateNewTissueType(request, response);
			}

			// called from newDelTissue.jsp when creating a new tissue with a master tissue
			else if (appAction.equalsIgnoreCase("ajaxCreateNewTissueWithMaster")) {
				doAjaxCreateNewTissueWithMaster(request, response);
			}

			// called from newDelTissue.jsp when creating a new tissue without a master tissue
			else if (appAction.equalsIgnoreCase("ajaxCreateNewTissueWithoutMaster")) {
				doAjaxCreateNewTissueWithoutMaster(request, response);
			}

			// called from newDelTissue.jsp when creating a new tissue with a master tissue and
			// duplicating the master tissue's eav data
			else if (appAction.equalsIgnoreCase("ajaxCreateNewTissueWithoutMaster")) {
				doAjaxDuplicateTissueEAVModalities(request, response);
			}

			// called from newDelTissue.jsp when displaying the tissue Type grid
			else if (appAction.equalsIgnoreCase("ajaxLoadTissueTypesFull")) {
				doAjaxLoadTissueTypesFull(request, response);
			}

			// called from newDelTissue.jsp when deleting a tissue
			else if (appAction.equalsIgnoreCase("ajaxDeleteTissue")) {
				doAjaxDeleteTissue(request, response);
			}

			// called from extractionList.jsp via the dataprocessor
			else if (appAction.equalsIgnoreCase("dhtmlxGridUpdateExtractions")) {
				doDHTMLXGRIDUpdateExtractions(request, response);
			}

			// called from tissueList.jsp via the dataprocessor
			else if (appAction.equalsIgnoreCase("dhtmlxGridUpdateTissues")) {
				doDHTMLXGRIDUpdateTissues(request, response);
			}

			else if (appAction.equalsIgnoreCase("dhtmlxToolbarGetVarListXML")) {
				doDHTMLXTOOLBARGetVarList(request, response, "XML");
			}

			else if (appAction.equalsIgnoreCase("dhtmlxToolbarGetVarListJSON")) {
				doDHTMLXTOOLBARGetVarList(request, response, "JSON");
			}

			// called from extractionImport.jsp via dhtmlxVault
			else if (appAction.equalsIgnoreCase("doLoadExtractionImportFile")) {
				doLoadExtractionImportFile(request, response);
			}

			// called from variableImport.jsp via dhtmlxVault
			// else if (appAction.equalsIgnoreCase("doLoadImportEAVDataFile")) {
			// doLoadImportEAVDataFile(request, response);
			// }
		}
		else {
			doReturnToIndex(request, response);
		}
	}

	private void doAjaxDuplicateTissueEAVModalities(HttpServletRequest request,
		HttpServletResponse response) throws IOException {
		String chcIDoriginal = request.getParameter("chcIDoriginal");
		String tissueTypeIDoriginal = request.getParameter("tissueTypeIDoriginal");
		String chcIDnew = request.getParameter("chcIDnew");
		String tissueTypeIDnew = request.getParameter("tissueTypeIDnew");
		Tissue originalTissue = new Tissue(Integer.parseInt(chcIDoriginal), tissueTypeIDoriginal);
		Tissue newTissue = new Tissue(Integer.parseInt(chcIDnew), tissueTypeIDnew);

		try {
			eavModalityDAO.duplicateModalities(originalTissue, newTissue);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, true);
		}
	}

	private void
		doAjaxLoadTissueTypesFull(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		try {
			List<TissueType> list = tissueTypeDAO.list(true);
			response.setContentType("text/xml");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(DHTMLXWriter.getInstance().writeDHTMLXTissueTypeGrid(list));
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, true);
		}

	}

	private void doAjaxDeleteTissue(HttpServletRequest request, HttpServletResponse response)
		throws IOException {
		String chcID = request.getParameter("chcID");
		String tissueTypeID = request.getParameter("tissueTypeID");
		try {
			Tissue tissue = tissueDAO.find(Integer.parseInt(chcID), tissueTypeID);
			if (tissue != null) {
				int dissociatedTissues = tissueDAO.dissociateMasterTissue(tissue);
				tissueDAO.delete(tissue);
				response.setContentType("text/plain");
				response.setCharacterEncoding("utf-8");
				response.getWriter().write(Integer.toString(dissociatedTissues));
			}
		}
		catch (NumberFormatException e) {
			handleAjaxException(new Exception("The chc ID  given (" + chcID
				+ ") is not a valid integer !"), response, true, true);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, true);
		}

	}

	private void doAjaxAssociateNewTissueWithMaster(HttpServletRequest request,
		HttpServletResponse response) throws IOException {
		String tissueCHCID = request.getParameter("tissueCHCID");
		String tissueTissueTypeID = request.getParameter("tissueTissueTypeID");
		String masterTissueCHCID = request.getParameter("masterTissueCHCID");
		String masterTissueTypeID = request.getParameter("masterTissueTypeID");
		try {
			Tissue tissue = tissueDAO.find(Integer.parseInt(tissueCHCID), tissueTissueTypeID);
			Tissue masterTissue =
				tissueDAO.find(Integer.parseInt(masterTissueCHCID), masterTissueTypeID);
			if (tissue == null) {
				handleAjaxException(new Exception("This tissue doesn't exist in the database !!!"),
					response, true, false);
			}
			else if (tissue.getMasterTissue() != null) {
				handleAjaxException(new Exception("This tissue (" + tissue
					+ ") already has a Master Tissue (" + tissue.getMasterTissue() + ") !!!"),
					response, true, false);
			}
			else if (masterTissue == null) {
				handleAjaxException(new Exception("This Master Tissue (" + masterTissue
					+ ") doesn't exist in the database !!!"), response, true, false);
			}
			else {
				tissue.setMasterTissue(masterTissue);
				tissueDAO.save(tissue);
			}

		}
		catch (NumberFormatException e) {
			handleAjaxException(new Exception(tissueCHCID + "is not a valid integer !"), response,
				true, false);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}

	}

	private void doAjaxDissociateMasterTissue(HttpServletRequest request,
		HttpServletResponse response) throws IOException {
		String tissueCHCID = request.getParameter("tissueCHCID");
		String tissueTypeID = request.getParameter("tissueTypeID");
		try {
			Tissue tissue = tissueDAO.find(Integer.parseInt(tissueCHCID), tissueTypeID);
			if (tissue == null) {
				handleAjaxException(new Exception("This tissue doesn't exist in the database !!!"),
					response, true, false);
			}
			else if (tissue.getMasterTissue() == null) {
				handleAjaxException(new Exception("This tissue (" + tissue
					+ ") doesn't have a Master Tissue (" + tissue.getMasterTissue() + ") !!!"),
					response, true, false);
			}
			else {
				tissue.setMasterTissue(null);
				tissueDAO.save(tissue);
			}

		}
		catch (NumberFormatException e) {
			handleAjaxException(new Exception(tissueCHCID + "is not a valid integer !"), response,
				true, false);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}

	}

	private void doAjaxCreateNewTissueWithoutMaster(HttpServletRequest request,
		HttpServletResponse response) throws IOException {
		String newTissueCHCID = request.getParameter("newTissueCHCID");
		String newTissueTissueTypeID = request.getParameter("newTissueTissueTypeID");
		if (newTissueCHCID != null && newTissueCHCID.trim().length() > 0
			&& newTissueTissueTypeID != null && newTissueTissueTypeID.trim().length() > 0) {

			Tissue newTissue = new Tissue(Integer.parseInt(newTissueCHCID), newTissueTissueTypeID);
			try {
				tissueDAO.save(newTissue);
			}
			catch (DAOException e) {
				handleAjaxException(e, response, true, false);
			}
		}
	}

	private void doAjaxCreateNewTissueWithMaster(HttpServletRequest request,
		HttpServletResponse response) throws IOException {
		String newTissueCHCID = request.getParameter("newTissueCHCID");
		String newTissueTissueTypeID = request.getParameter("newTissueTissueTypeID");
		String masterTissueCHCID = request.getParameter("masterTissueCHCID");
		String masterTissueTypeID = request.getParameter("masterTissueTypeID");
		if (newTissueCHCID != null && newTissueCHCID.trim().length() > 0
			&& newTissueTissueTypeID != null && newTissueTissueTypeID.trim().length() > 0
			&& masterTissueCHCID != null && masterTissueCHCID.trim().length() > 0
			&& masterTissueTypeID != null && masterTissueTypeID.trim().length() > 0) {
			Tissue newTissue = new Tissue(Integer.parseInt(newTissueCHCID), newTissueTissueTypeID);
			Tissue masterTissue =
				new Tissue(Integer.parseInt(masterTissueCHCID), masterTissueTypeID);
			newTissue.setMasterTissue(masterTissue);
			try {
				tissueDAO.save(newTissue);
			}
			catch (DAOException e) {
				handleAjaxException(e, response, true, false);
			}
		}

	}

	private void
		doAjaxCreateNewTissueType(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		String newTissueTypeID = request.getParameter("newTissueTypeID");
		String description = request.getParameter("description");
		if (newTissueTypeID != null && newTissueTypeID.trim().length() > 0) {
			TissueType tissueType = new TissueType(newTissueTypeID);
			tissueType.setTissueTypeDescription(description);
			try {
				tissueTypeDAO.save(tissueType);
			}
			catch (DAOException e) {
				handleAjaxException(e, response, true, false);
			}
		}

	}

	private void
		doAjaxLoadAllEAVVariables(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		LinkedHashMap<String, HashMap<String, String>> simpleVarHashMap =
			new LinkedHashMap<String, HashMap<String, String>>();
		try {
			List<EAVVariable> eavVarsList = eavVariableDAO.list(false, true);
			for (EAVVariable var : eavVarsList) {
				HashMap<String, String> map = new HashMap<String, String>();
				map.put("humanReadableName", var.getHumanReadableName());
				map.put("dataType", var.getDataType());
				simpleVarHashMap.put(var.getVariableName(), map);

			}
			Gson gson = new Gson();
			String varArrayJSON = gson.toJson(simpleVarHashMap);
			response.setContentType("application/JSON");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(varArrayJSON);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}

	}

	private void doAjaxLoadTissueTypes(HttpServletRequest request, HttpServletResponse response)
		throws IOException {

		try {
			ArrayList<TissueType> list = tissueTypeDAO.list(false);
			ArrayList<String> list2 = new ArrayList<String>();
			for (TissueType tt : list)
				list2.add(tt.getTissueTypeID());
			response.setContentType("application/JSON");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(new Gson().toJson(list2));
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, true);
		}

	}

	private void doAjaxUpdateModalityByVariableNameAndModalityValue(HttpServletRequest request,
		HttpServletResponse response) throws IOException {
		String variableName = request.getParameter("variableName");
		String oldModalityValue = request.getParameter("oldModalityValue");
		String newModalityValue = request.getParameter("newModalityValue");
		try {
			EAVVariable eavVariable = eavVariableDAO.find(variableName);
			if (eavVariableDAO.existsByID(eavVariable)) {
				int modifiedRows =
					eavModalityDAO.updateByVariableNameAndModalityValue(newModalityValue,
						eavVariable, oldModalityValue);
				response.setCharacterEncoding("UTF-8");
				response.setContentType("text/plain");
				response.getWriter().write(Integer.toString(modifiedRows));
			}
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, true);
		}

	}

	private void doAjaxUpdateTissueEAVModalities(HttpServletRequest request,
		HttpServletResponse response) {
		String jsonString = request.getParameter("newModalities");
		Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
		HashMap<String, String> map =
			gson.fromJson(jsonString, new TypeToken<HashMap<String, String>>() {
			}.getType());
		Tissue tissueToUpdate =
			new Tissue(Integer.parseInt(map.get("chcID")), map.get("tissueTypeID"));
		for (String key : map.keySet()) {
			if (!key.equalsIgnoreCase("chcID") && !key.equalsIgnoreCase("tissueTypeID")) {
				String eavVariableName = key;
				try {
					EAVVariable var = eavVariableDAO.find(eavVariableName);
					String eavModalityValue = map.get(key);
					EAVModality mod = new EAVModality(var, tissueToUpdate);
					mod.setDeprecated(false);
					mod.setModality(eavModalityValue);
					if (eavModalityValue.trim().length() < 1
						|| eavModalityValue.trim().equalsIgnoreCase("null")) {
						eavModalityDAO.delete(mod);
					}
					else {
						eavModalityDAO.save(mod);
					}
				}
				catch (DAOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private void doAjaxLoadUnsetGenericVariables(HttpServletRequest request,
		HttpServletResponse response) throws IOException {
		String tissue_chcID = request.getParameter("tissue_chcID");
		String tissue_tissueTypeID = request.getParameter("tissue_tissueTypeID");
		try {
			Tissue tissue = new Tissue(Integer.parseInt(tissue_chcID), tissue_tissueTypeID);
			List<EAVVariable> list = eavVariableDAO.listUnsetVariable(tissue);
			response.setContentType("application/JSON");
			response.setCharacterEncoding("UTF-8");
			String jsonResponse = new Gson().toJson(list);
			response.getWriter().write(jsonResponse);
		}
		catch (NumberFormatException e) {
			handleAjaxException(e, response, true, true);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}
	}

	private void doAjaxLoadTissueList(HttpServletRequest request, HttpServletResponse response)
		throws IOException, ServletException {
		try {
			List<Tissue> tissueList = tissueDAO.list();
			// HashMap<String>
			Gson gson = new Gson();
			String jsonResponse = gson.toJson(tissueList);
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/JSON");
			response.getWriter().write(jsonResponse);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}
	}

	private void doAjaxUpdateEAVVariable(HttpServletRequest request, HttpServletResponse response)
		throws IOException {
		String varToUpdateJSON = request.getParameter("varToUpdateJSON");
		Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
		EAVVariable varToUpdate = gson.fromJson(varToUpdateJSON, EAVVariable.class);
		try {
			eavVariableDAO.update(varToUpdate);

		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}

	}

	private void doAjaxGetModalityGrid(HttpServletRequest request, HttpServletResponse response)
		throws IOException {
		String eavVariableID = request.getParameter("eavVariableID");
		try {
			Thread.sleep(200);
			EAVVariable var = eavVariableDAO.find(Long.parseLong(eavVariableID));
			HashMap<String, Integer> modalities = eavVariableDAO.getModalitiesInfo(var);
			response.setContentType("text/xml");
			response.setCharacterEncoding("UTF-8");
			String responseText =
				DHTMLXWriter.getInstance().writeDHTMLXGridEAVVariableModalities(modalities);
			response.getWriter().write(responseText);

		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}
		catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void doAjaxLoadOldModalities(HttpServletRequest request, HttpServletResponse response)
		throws IOException {
		String eavVariableID = request.getParameter("eavVariableID");
		try {
			Thread.sleep(200);
			EAVVariable var = eavVariableDAO.find(Long.parseLong(eavVariableID));
			if (eavVariableDAO.existsByID(var)) {
				List<String> modalities = eavModalityDAO.listDistinctValues(var);

				Gson gson = new Gson();
				String modalitiesListJSONString = gson.toJson(modalities);
				response.setContentType("application/JSON");
				response.setCharacterEncoding("UTF-8");
				response.getWriter().write(modalitiesListJSONString);
			}
		}
		catch (NumberFormatException e) {
			handleAjaxException(e, response, true, false);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, true);
		}
		catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void doAjaxLoadModalityGridAndModalityList(HttpServletRequest request,
		HttpServletResponse response) throws IOException {
		String eavVariableID = request.getParameter("eavVariableID");
		try {
			Thread.sleep(200);
			EAVVariable var = eavVariableDAO.find(Long.parseLong(eavVariableID));
			if (eavVariableDAO.existsByID(var)) {
				HashMap<String, Integer> modalities = eavVariableDAO.getModalitiesInfo(var);
				String gridXML =
					DHTMLXWriter.getInstance().writeDHTMLXGridEAVVariableModalities(modalities);
				Gson gson = new Gson();
				String modalitiesJSON = gson.toJson(modalities);

				ArrayList<String> fullResponseJSON = new ArrayList<String>();
				fullResponseJSON.add(modalitiesJSON);
				fullResponseJSON.add(gridXML);
				response.setContentType("application/json");
				response.setCharacterEncoding("UTF-8");
				response.getWriter().write(gson.toJson(fullResponseJSON));
			}
		}
		catch (InterruptedException e) {
			// TODO
		}
		catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, true);
		}
	}

	private void doAjaxLoadTissue(HttpServletRequest request, HttpServletResponse response)
		throws IOException {
		String chcID = request.getParameter("chcID");
		String tissueTypeID = request.getParameter("tissueTypeID");
		try {
			Tissue tissue = new Tissue(Integer.parseInt(chcID), tissueTypeID);
			if (tissueDAO.exists(tissue)) {
				tissue = tissueDAO.find(Integer.parseInt(chcID), tissueTypeID);
				tissueDAO.fetchTissueEAVData(tissue);
				tissueDAO.fetchTissueQuantityAfterLastManipulation(tissue);
				tissueDAO.listAssociatedTissues(tissue);
				response.setContentType("application/JSON");
				response.setCharacterEncoding("UTF-8");
				String jsonResponse = new Gson().toJson(tissue);
				response.getWriter().write(jsonResponse);
			}
			else {
				handleAjaxException(new Exception("The tissue " + tissue
					+ " doesn't exist in the database !"), response, true, true);
			}
		}
		catch (NumberFormatException e) {
			handleAjaxException(new Exception("The chc ID submitted (" + chcID
				+ ") is not a valid integer !"), response, true, true);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
			e.printStackTrace();
		}

	}

	private void doAjaxFetchVar(HttpServletRequest request, HttpServletResponse response)
		throws IOException, ServletException {
		try {
			String eavVariableID = request.getParameter("eavVariableID");
			EAVVariable eavVariable = eavVariableDAO.find(Long.parseLong(eavVariableID));
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/JSON");
			String jsonResponse = new Gson().toJson(eavVariable);
			response.getWriter().write(jsonResponse);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}

	}

	private void doAjaxFetchVarNames(HttpServletRequest request, HttpServletResponse response)
		throws IOException, ServletException {
		List<String> eavVarNames = null;
		try {
			eavVarNames = eavVariableDAO.listNames();
			request.setAttribute("eavVarNames", eavVarNames);
			request.getRequestDispatcher("includes/ajax/eavVarsSelect.jsp").forward(request,
				response);

		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}

	}

	private void doAjaxDeleteVars(HttpServletRequest request, HttpServletResponse response)
		throws IOException {
		String varsToDelete = request.getParameter("varsToDelete");
		String[] varsToDeleteArray = varsToDelete.split("\\,");
		List<EAVVariable> deletedVarList = new ArrayList<EAVVariable>();
		try {
			for (String variableID : varsToDeleteArray) {
				EAVVariable var = eavVariableDAO.find(Long.parseLong(variableID));
				int affectedRows = eavVariableDAO.delete(var);
				if (affectedRows > 0)
					deletedVarList.add(var);
			}
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/JSON");
			Gson gson = new Gson();
			response.getWriter().write(gson.toJson(deletedVarList));
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}
	}

	private void doAjaxSubmitVar(HttpServletRequest request, HttpServletResponse response)
		throws IOException {
		String variableName = request.getParameter("variableName");
		String humanReadableName = request.getParameter("humanReadableName");
		String dataType = request.getParameter("dataType");
		boolean isDeprecated = request.getParameter("isDeprecated").equalsIgnoreCase("YES");
		String description = request.getParameter("description");

		EAVVariable newVar = new EAVVariable(variableName);
		newVar.setCreationDate(new Date());
		newVar.setDataType(dataType);
		newVar.setDeprecated(isDeprecated);
		newVar.setDescription(description);
		newVar.setHumanReadableName(humanReadableName);

		try {
			if (!eavVariableDAO.existsByName(newVar)) {
				eavVariableDAO.create(newVar);
				response.setContentType("application/JSON");
				response.setCharacterEncoding("UTF-8");
				Gson gson = new Gson();
				String jsonResponse = gson.toJson(newVar);
				response.getWriter().write(jsonResponse);
			}
			else {
				handleAjaxException(new Exception(
					"A variable with the same Full Name already exists in the database"), response,
					true, true);
			}
		}
		catch (DAOException e) {
			handleAjaxException(e, response, false, false);
			e.printStackTrace();
		}

	}

	// private void doLoadImportEAVDataFile(HttpServletRequest request, HttpServletResponse
	// response) {
	// String importFileName = null;
	//
	// if (request.getParameter("importFileName") != null) {
	// importFileName = request.getParameter("importFileName");
	// }
	// }

	private void
		doLoadExtractionImportFile(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String importFileName = null;

		if (request.getParameter("importFileName") != null) {
			importFileName = request.getParameter("importFileName");
			try {
				LinkedHashMap<String, String> importFileInfo = null;
				importFileInfo = ExtractionFeeder.getInstance().analyzeFile(importFileName);

				LinkedHashMap<String, ArrayList<TissueExtraction>> importFileContent = null;
				LinkedHashMap<String, HashMap<TissueExtraction, List<TissueExtraction>>> importFileContentDuplicates =
					new LinkedHashMap<String, HashMap<TissueExtraction, List<TissueExtraction>>>();

				try {
					importFileContent =
						ExtractionFeeder.getInstance().analyzeFileContent(importFileName,
							importFileInfo);
					request.setAttribute("importFileContent", importFileContent);

					// RNA DUPLICATE ANALYSIS
					if (importFileContent.get("RNAExtractions") != null
						&& importFileContent.get("RNAExtractions").size() > 0) {
						HashMap<TissueExtraction, List<TissueExtraction>> rnaDuplicates =
							new HashMap<TissueExtraction, List<TissueExtraction>>();
						for (TissueExtraction extr : importFileContent.get("RNAExtractions")) {
							List<TissueExtraction> rnaExtractionDuplicates =
								tissueExtractionDAO.listSimilar(extr);
							if (rnaExtractionDuplicates.size() > 0)
								rnaDuplicates.put(extr, rnaExtractionDuplicates);
						}
						importFileContentDuplicates.put("RNAExtractions", rnaDuplicates);
					}

					// RNA DUPLICATE ANALYSIS
					if (importFileContent.get("DNAExtractions") != null
						&& importFileContent.get("DNAExtractions").size() > 0) {
						HashMap<TissueExtraction, List<TissueExtraction>> dnaDuplicates =
							new HashMap<TissueExtraction, List<TissueExtraction>>();
						for (TissueExtraction extr : importFileContent.get("DNAExtractions")) {
							List<TissueExtraction> dnaExtractionDuplicates =
								tissueExtractionDAO.listSimilar(extr);
							if (dnaExtractionDuplicates.size() > 0)
								dnaDuplicates.put(extr, dnaExtractionDuplicates);
						}
						importFileContentDuplicates.put("DNAExtractions", dnaDuplicates);
					}
					request
						.setAttribute("importFileContentDuplicates", importFileContentDuplicates);
				}
				catch (FeederException e) {
					String message = e.getMessage();
					request.setAttribute("importError", message);
				}
				finally {

					// GET FILE INFO
					request.setAttribute("importFileInfo", importFileInfo);
					request.setAttribute("importFileName", importFileName);

					// FORWARDING TO JSP SNIPPET
					request.getRequestDispatcher("includes/ajax/importFileAnalysis.jsp").forward(
						request, response);
				}
			}
			catch (InvalidFormatException e) {
				handleAjaxException(e, response, true, false);
			}
			catch (DAOException e) {
				handleAjaxException(e, response, true, false);
				e.printStackTrace();
			}
		}
		else {
			handleAjaxException(new Exception("Problem while loading import file."), response,
				true, false);
		}

	}

	private void doAjaxLoadVarsArray(HttpServletRequest request, HttpServletResponse response)
		throws IOException {
		LinkedHashMap<String, HashMap<String, String>> simpleVarHashMap =
			new LinkedHashMap<String, HashMap<String, String>>();
		try {
			List<EAVVariable> eavVarsList = eavVariableDAO.list(false, true);
			for (EAVVariable var : eavVarsList) {
				HashMap<String, String> map = new HashMap<String, String>();
				map.put("humanReadableName", var.getHumanReadableName());
				map.put("nMod", Integer.toString(var.getnModalities()));
				map.put("dataType", var.getDataType());
				simpleVarHashMap.put(var.getVariableName(), map);

			}
			Gson gson = new Gson();
			String varArrayJSON = gson.toJson(simpleVarHashMap);
			response.setContentType("application/JSON");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(varArrayJSON);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}
	}

	private void doAjaxLoadVarsComboBoxes(HttpServletRequest request, HttpServletResponse response)
		throws IOException, ServletException {
		try {
			List<EAVVariable> eavVarsList = eavVariableDAO.list(false, false);
			List<EAVVariable> miscEAVvarList = new ArrayList<EAVVariable>();

			List<EAVVariable> clinicalDataEAVvarList =
				eavVariableDAO.listByPrefix("clinicaldata_", false);
			List<EAVVariable> pathologicalDataEAVvarList =
				eavVariableDAO.listByPrefix("pathologicaldata_", false);
			List<EAVVariable> riskFactorsEAVvarList =
				eavVariableDAO.listByPrefix("riskfactor_", false);
			List<EAVVariable> ntLiverEAVvarList = eavVariableDAO.listByPrefix("ntliver_", false);
			List<EAVVariable> mutationEAVvarList = eavVariableDAO.listByPrefix("mutation_", false);
			List<EAVVariable> ihcDataEAVvarList = eavVariableDAO.listByPrefix("ihcdata_", false);
			List<EAVVariable> biologicalDataEAVvarList =
				eavVariableDAO.listByPrefix("biologicaldata_", false);
			List<EAVVariable> familyDataEAVvarList =
				eavVariableDAO.listByPrefix("familydata_", false);

			List<EAVVariable> survivalAndRelapseDataEAVvarList =
				eavVariableDAO.listByPrefix("relapseData_", false);
			survivalAndRelapseDataEAVvarList.addAll(eavVariableDAO.listByPrefix("survivalData_",
				false));

			for (EAVVariable var : eavVarsList) {
				if (!clinicalDataEAVvarList.contains(var)
					&& !pathologicalDataEAVvarList.contains(var)
					&& !riskFactorsEAVvarList.contains(var) && !ntLiverEAVvarList.contains(var)
					&& !mutationEAVvarList.contains(var) && !ihcDataEAVvarList.contains(var)
					&& !biologicalDataEAVvarList.contains(var)
					&& !familyDataEAVvarList.contains(var)
					&& !survivalAndRelapseDataEAVvarList.contains(var)) {
					miscEAVvarList.add(var);
				}
			}

			// request.setAttribute("eavVarsList", eavVarsList);

			request.setAttribute("clinicalDataEAVvarList", clinicalDataEAVvarList);
			request.setAttribute("biologicalDataEAVvarList", biologicalDataEAVvarList);
			request.setAttribute("riskFactorsEAVvarList", riskFactorsEAVvarList);
			request.setAttribute("pathologicalDataEAVvarList", pathologicalDataEAVvarList);
			request.setAttribute("ntLiverEAVvarList", ntLiverEAVvarList);
			request.setAttribute("ihcDataEAVvarList", ihcDataEAVvarList);
			request.setAttribute("mutationEAVvarList", mutationEAVvarList);
			request.setAttribute("miscEAVvarList", miscEAVvarList);
			request.setAttribute("familyDataEAVvarList", familyDataEAVvarList);
			request.setAttribute("survivalAndRelapseDataEAVvarList",
				survivalAndRelapseDataEAVvarList);

			request.getRequestDispatcher("includes/ajax/eavVarsComboBoxes.jsp").forward(request,
				response);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}

	}

	private void doDHTMLXTOOLBARGetVarList(HttpServletRequest request,
		HttpServletResponse response, String responseType) throws IOException {
		try {
			List<EAVVariable> list = eavVariableDAO.list(false, false);
			String responseText = null;
			response.setCharacterEncoding("UTF-8");

			if (responseType.equalsIgnoreCase("XML")) {
				response.setContentType("text/xml");
				responseText = DHTMLXWriter.getInstance().writeDHTMLXTissueToolbarXML(list);
			}
			else if (responseType.equalsIgnoreCase("JSON")) {
				response.setContentType("application/json");
				Gson gson = new Gson();
				responseText = gson.toJson(list);
			}
			response.getWriter().write(responseText);
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}
	}

	private void
		doDHTMLXGRIDUpdateTissues(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		@SuppressWarnings("unchecked")
		Map<Object, Object> parametersMap = request.getParameterMap();
		Integer chcID = Integer.parseInt(request.getParameter("ID"));
		String tissueTypeID = request.getParameter("Type");
		Tissue tempTissue = new Tissue(chcID, tissueTypeID);
		List<String> validVariableNames;
		try {
			validVariableNames = eavVariableDAO.listNames();
			for (Object paramName : parametersMap.keySet()) {
				String putativeModality = (request.getParameter((String) paramName));

				if (paramName instanceof String
					&& validVariableNames.contains(((String) paramName))) {
					EAVVariable var = eavVariableDAO.find((String) paramName);
					if (putativeModality != null && putativeModality.trim().length() > 0) {
						putativeModality = putativeModality.replaceAll("\\&gt;", ">");
						putativeModality = putativeModality.replaceAll("\\&lt\\;", "<");
						EAVModality mod = new EAVModality(var, tempTissue, putativeModality, false);
						if (!eavModalityDAO.exists(mod, true))
							eavModalityDAO.save(mod);
					}
					else {
						EAVModality modToDelete = new EAVModality(var, tempTissue);
						if (eavModalityDAO.exists(modToDelete, false)) {
							eavModalityDAO.delete(modToDelete);
						}
					}

				}
			}
			StringBuffer responseString = new StringBuffer("<data>");
			responseString.append("<action type=\"update\" sid=\"" + tempTissue + "\" tid=\""
				+ tempTissue + "\" />");
			responseString.append("</data>");
			response.setContentType("text/xml");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(responseString.toString());
		}
		catch (DAOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void doDHTMLXGRIDUpdateExtractions(HttpServletRequest request,
		HttpServletResponse response) throws IOException {
		HashMap<String, String> fieldsAndValues = new HashMap<String, String>();

		String requestManipulationID = request.getParameter("gr_id");
		String requestchcID = request.getParameter("chcID");
		String requestTissueTypeID = request.getParameter("tissueTypeID");
		String requestExperimenter = request.getParameter("experimenter");
		String requestConcentration = request.getParameter("concentration");
		String requestFinalVolume = request.getParameter("finalVolume");
		String requestQuantity = request.getParameter("quantityExtracted");
		String requestEmptyTube = request.getParameter("emptyTube");
		String requestGelQuality = request.getParameter("gelQuality");
		String requestQuantityLeft = request.getParameter("quantityTissueLeftAfterManipulation");
		String requestDate = request.getParameter("manipulationDate");
		String requestExtractionType = request.getParameter("extractionType");
		String requestExtractionComment = request.getParameter("extractionComment");

		// RNA EXTRACTIONS
		String requestDO260_280 = request.getParameter("do260_280");
		String requestAgilentDate = request.getParameter("agilentDate");
		String requestAgilent_28S_18S = request.getParameter("agilent_28S_18S");
		String requestExtractionMethod = request.getParameter("extractionMethod");

		fieldsAndValues.put("manipulationID", requestManipulationID);
		fieldsAndValues.put("chcID", requestchcID);
		fieldsAndValues.put("tissueTypeID", requestTissueTypeID);
		fieldsAndValues.put("concentration", requestConcentration);
		fieldsAndValues.put("finalVolume", requestFinalVolume);
		fieldsAndValues.put("experimenter", requestExperimenter);
		fieldsAndValues.put("quantityExtracted", requestQuantity);

		// TODO code metier a mettre dans le modele !!!!
		fieldsAndValues.put("emptyTube", requestEmptyTube.equalsIgnoreCase("true")
			|| requestEmptyTube.equalsIgnoreCase("oui") ? "1"
			: "0");

		fieldsAndValues.put("gelQuality", requestGelQuality);
		fieldsAndValues.put("quantityTissueLeftAfterManipulation", requestQuantityLeft);
		fieldsAndValues.put("manipulationDate", requestDate);
		fieldsAndValues.put("extractionType", requestExtractionType);
		fieldsAndValues.put("extractionComment", requestExtractionComment);

		// RNA EXTRACTIONS
		fieldsAndValues.put("do260_do280", requestDO260_280);
		fieldsAndValues.put("agilentDate", requestAgilentDate);
		fieldsAndValues.put("agilent_28S_18S", requestAgilent_28S_18S);
		fieldsAndValues.put("extractionMethod", requestExtractionMethod);

		try {
			tissueExtractionDAO.updateWithVariableParameters(fieldsAndValues);
			StringBuffer responseString = new StringBuffer("<data>");
			responseString.append("<action type=\"update\" sid=\"" + requestManipulationID
				+ "\" tid=\"" + requestManipulationID + "\" />");
			responseString.append("</data>");
			response.setContentType("text/xml");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(responseString.toString());
		}
		catch (DAOException e) {
			StringBuffer responseString = new StringBuffer("<data>");
			responseString.append("<action type=\"error\" sid=\"" + requestManipulationID
				+ "\" tid=\"" + requestManipulationID + "\">");
			responseString.append(e.getMessage());
			responseString.append("</action></data>");
			response.setContentType("text/xml");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(responseString.toString());
			System.err.print(e.getStackTrace());
		}
	}

	// private void doDisplayTissue(HttpServletRequest request, HttpServletResponse response)
	// throws ServletException, IOException {
	// DisplayTissueForm displayTissueForm = new DisplayTissueForm(tissueDAO, tissueExtractionDAO);
	// request.setAttribute(ATTRIBUTE_DISPLAY_TISSUE_FORM, displayTissueForm);
	//
	// Tissue tissue = displayTissueForm.displayTissue(request);
	// request.setAttribute(ATTRIBUTE_TISSUE, tissue);
	//
	// request.getRequestDispatcher(ATTRIBUTE_DISPLAY_TISSUE_VIEW).forward(request, response);
	// }

	private void doDisplayTissue2(HttpServletRequest request, HttpServletResponse response)
		throws IOException, ServletException {

		Integer chcID = Integer.parseInt(request.getParameter("chcID"));
		String tissueTypeID = request.getParameter("tissueTypeID");

		Tissue tissue;
		try {
			tissue = tissueDAO.find(chcID, tissueTypeID);
			if (tissue != null) {
				// tissueDAO.fetchTissueQuantityAfterLastManipulation(tissue);
				// tissueDAO.listAssociatedTissues(tissue);
				// tissueDAO.fetchTissueEAVData(tissue);
				request.setAttribute(ATTRIBUTE_TISSUE, tissue);
				request.getRequestDispatcher(ATTRIBUTE_DISPLAY_TISSUE_VIEW).forward(request,
					response);
			}
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, true);
		}

	}

	private void doReturnToIndex(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		request.getRequestDispatcher(ATTRIBUTE_INDEX_PAGE_VIEW).forward(request, response);
	}

	private void doListExtractions(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		ExtractionListForm extractionListForm =
			new ExtractionListForm(tissueDAO, tissueExtractionDAO);
		request.setAttribute(ATTRIBUTE_LIST_EXTRACTION_FORM, extractionListForm);

		List<TissueExtraction> extractionList = extractionListForm.listExtractions();
		request.setAttribute(ATTRIBUTE_EXTRACTION_LIST, extractionList);

		request.getRequestDispatcher(ATTRIBUTE_LIST_EXTRACTION_VIEW).forward(request, response);
	}

	private void doAjaxListExtractions(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {

		List<TissueExtraction> extractionList;
		String tissueJSONString = request.getParameter("tissueJSONArray");
		ArrayList<Tissue> tissuesOfInterest = null;
		Gson gson = new Gson();
		if (tissueJSONString != null && tissueJSONString.length() > 0) {
			tissuesOfInterest = new ArrayList<Tissue>();
			String[] tissueArray = gson.fromJson(tissueJSONString, String[].class);
			for (int i = 0; i < tissueArray.length; i++) {
				if (Tissue.isRawCHCIDValid(tissueArray[i]))
					tissuesOfInterest.add(new Tissue(tissueArray[i]));
			}
		}

		try {
			extractionList = tissueExtractionDAO.list(tissuesOfInterest);

			ServletOutputStream servletOutputStream = response.getOutputStream();

			DHTMLXWriter.getInstance().writeXMLTissueExtractionGridToOutputStream(extractionList,
				servletOutputStream);
			response.setContentType("text/xml");
			response.setCharacterEncoding("UTF-8");
			servletOutputStream.flush();
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}
	}

	private void doAjaxListTissues(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {

		List<Tissue> tissueList;
		try {

			Gson gson = new Gson();
			String eavVarJSONString = request.getParameter("eavVarJSONArray");
			String tissueJSONString = request.getParameter("tissueJSONArray");
			ArrayList<Tissue> tissuesOfInterest = null;
			if (tissueJSONString != null && tissueJSONString.length() > 0) {
				tissuesOfInterest = new ArrayList<Tissue>();
				String[] tissueArray = gson.fromJson(tissueJSONString, String[].class);
				for (int i = 0; i < tissueArray.length; i++) {
					if (Tissue.isRawCHCIDValid(tissueArray[i]))
						tissuesOfInterest.add(new Tissue(tissueArray[i]));
				}
			}
			Boolean showTissuesWithNoModalities = false;
			if (request.getParameter("showTissuesWithNoModalities") != null)
				showTissuesWithNoModalities =
					request.getParameter("showTissuesWithNoModalities").equalsIgnoreCase("true");
			Boolean showTissueQuantities = false;
			if (request.getParameter("showTissueQuantities") != null)
				showTissueQuantities =
					request.getParameter("showTissueQuantities").equalsIgnoreCase("true");
			String[] eavVariableNamesToDisplay = gson.fromJson(eavVarJSONString, String[].class);
			tissueList =
				tissueDAO.list(showTissueQuantities, eavVariableNamesToDisplay, tissuesOfInterest,
					showTissuesWithNoModalities);
			ServletOutputStream servletOutStream = response.getOutputStream();
			DHTMLXWriter.getInstance().writeXMLTissueGridToOutputStream(tissueList,
				eavVariableNamesToDisplay, showTissueQuantities, servletOutStream);

			response.setContentType("text/xml");
			response.setCharacterEncoding("UTF-8");
			servletOutStream.flush();
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}

	}

	private void doAjaxSaveGridFile(HttpServletRequest request, HttpServletResponse response)
		throws IOException {
		List<Tissue> tissueList;
		try {

			Gson gson = new Gson();
			String eavVarJSONString = request.getParameter("eavVarJSONArray");
			String tissueJSONString = request.getParameter("tissueJSONArray");
			String varHashString = request.getParameter("varHashJSONHash");

			String outputFormat = request.getParameter("outputFormat");

			ArrayList<Tissue> tissuesOfInterest = null;
			if (tissueJSONString != null && tissueJSONString.length() > 0
				&& tissueJSONString.indexOf("null") == -1) {
				tissuesOfInterest = new ArrayList<Tissue>();
				String[] tissueArray = gson.fromJson(tissueJSONString, String[].class);
				for (int i = 0; i < tissueArray.length; i++) {
					if (Tissue.isRawCHCIDValid(tissueArray[i]))
						tissuesOfInterest.add(new Tissue(tissueArray[i]));
				}
			}
			Boolean showTissuesWithNoModalities = false;
			if (request.getParameter("showTissuesWithNoModalities") != null)
				showTissuesWithNoModalities =
					request.getParameter("showTissuesWithNoModalities").equalsIgnoreCase("true");
			Boolean showTissueQuantities = false;
			if (request.getParameter("showTissueQuantities") != null)
				showTissueQuantities =
					request.getParameter("showTissueQuantities").equalsIgnoreCase("true");
			String[] eavVariableNamesToDisplay = gson.fromJson(eavVarJSONString, String[].class);

			HashMap<String, String> eavVariables =
				gson.fromJson(varHashString, new TypeToken<HashMap<String, String>>() {
				}.getType());

			tissueList =
				tissueDAO.list(showTissueQuantities, eavVariableNamesToDisplay, tissuesOfInterest,
					showTissuesWithNoModalities);

			ServletContext context = getServletContext();
			File directory = new File(context.getRealPath("/userFiles"));
			GridFileSaver cfs =
				new GridFileSaver((ArrayList<Tissue>) tissueList, eavVariables,
					showTissueQuantities);
			File file = null;
			if (outputFormat != null && outputFormat.trim().equalsIgnoreCase("CSV"))
				file = cfs.saveAsCSV(directory);
			else if (outputFormat != null && outputFormat.trim().equalsIgnoreCase("TAB"))
				file = cfs.saveAsTabTxt(directory);
			else if (outputFormat != null && outputFormat.trim().equalsIgnoreCase("XLS"))
				file = cfs.saveAsXLS(directory);
			else
				file = cfs.saveAsTabTxt(directory);

			if (file.exists()) {
				String fileName = file.getName();
				doSendFileLinkToClient(request, response, fileName);
			}

		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}
		catch (InvalidFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * This methods sends a file to the client via a standard download dialog (browser dependent)
	 * 
	 * @param request
	 * @param response
	 * @param fileName
	 *            the URI of the file that will be sent, il must refer to a location that de JRE can
	 *            reach
	 * @throws IOException
	 */
	private void doSendFileLinkToClient(HttpServletRequest request, HttpServletResponse response,
		String fileName) throws IOException {
		ServletContext context = getServletContext();
		String path = context.getContextPath();
		String linkToReturn =
			"<a target=\"_blank\" href='" + path + "/userFiles/" + fileName + "' >" + fileName
				+ "</a>";

		response.setContentType("text/plain");
		response.setCharacterEncoding("UTF-8");
		response.getWriter().write(linkToReturn);

	}

	private void doAjaxListVars(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		List<EAVVariable> varList;
		try {
			varList = eavVariableDAO.list(true, false);
			response.setContentType("text/xml");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(
				DHTMLXWriter.getInstance().writeEAVVarListTable(varList, true));
		}
		catch (DAOException e) {
			handleAjaxException(e, response, true, false);
		}
	}

	/**
	 * This function evaluates the message of any exception which should be notified to the end user
	 * after an AJAX call. After the message is evaluated, an ad hoc response (with a 500 status
	 * code and a short error message) is sent to the ajax calling function (which must implement it
	 * with an onFailure method)
	 * 
	 * @param e
	 *            the Exception which message will be evaluated
	 * @param response
	 *            the HttpServletResponse, which will be evaluated in the ajax calling function,
	 *            whose status code is set to 500.
	 * @param fullMessageOutput
	 *            TODO
	 * @param userException
	 *            TODO
	 * @throws IOException
	 */
	private void handleAjaxException(Exception e, HttpServletResponse response,
		Boolean fullMessageOutput, Boolean userException) throws IOException {
		response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		response.setContentType("text/xml");
		response.setCharacterEncoding("UTF-8");
		String responseText;
		if (!fullMessageOutput) {
			if (e.getMessage() != null) {
				if (e.getMessage().indexOf("Communications link failure") > -1) {
					responseText =
						"Connection to the database failed, please contact an administrator.<br/>";
				}
				else {
					responseText = "Unknown database error, please contact an administrator.<br/>";
				}
			}
			else {
				responseText = "Unknown error, please contact an administrator.<br/>";
			}
		}
		else {
			responseText =
				DHTMLXWriter.getInstance().writeHTMLErrorMessage(e.getMessage(), userException);
		}
		response.getWriter().write(responseText);

		e.printStackTrace(System.err);
	}

}
